<?php
	
	/**
	 * 文件上传类,只要存在一个文件条件不通过那么直接就返回false
	 * 将其他的文件也不上传
	 * @author Administrator
	 *
	 */
	class Upload{
		//默认允许上传的文件类型
		public $allowType;
		//默认存在上传的目录
		public $path;
		//默认允许上传的文件大小
		public $allowSize;
		//用于保存错误的成员属性 是一个数组
		public $error;
		//上传成功的文件名
		public $upFiles;
	
		
		/**
		 * 将类初始化的同时传入相应的保存路径和允许上传的文件类型还有上传
		 * 文件的大小allowType:为允许的类型，如果用了传入那么就是追加到本
		 * @param string $path
		 * @param array $allowType
		 * @param int $allowSize
		 */
		public function __construct($path=null,$allowType=null,$allowSize=null){
			
			//判断如果$path为null那么就使用配置文件中的配置项
			$path = is_null($path)?C('UPLOAD_PATH'):$path;
			//判断用户是否传入了path参数如果传入那么就替换当前$this->path属性中的值
			//处理路径  将\转为/再去除最右边的/ 再连接一次
			$this->path = rtrim(str_replace('\\', '/', $path),'/').'/';
			
			//如果用户传入了允许的类型那么就替换当前类中的允许的类型
			$this->allowType 	= is_null($allowType)?C('UPLOAD_ALLOWTYPE'):$allowType;
			//如果传入了size就替换
			$this->allowSize 	= is_null($allowSize)?C('UPLOAD_ALLOWSIZE'):$allowSize;
			
		}
	
		/**
		 * 将文件上传方法
		 */
		public function upFile(){
			//1、重组数组
			$fileArr = $this->resetArr();
			foreach($fileArr as $file){
				//2、过滤不符合条件的文件
				$this->filter($file);
				if($this->error){
					$this->error[] = $file['name'].'文件不符合上传规则请重新提交表单';
					return false;
				}
				//如果过滤文件的时候不存在错误那么才上传文件否则不上传文件
				//3、将文件上传 				
			}
			//当不存在错误 再上传文件
// 			if(!$this->error){
				foreach($fileArr as $file){
					$this->move($file);
				}	
// 			}		
		}
		
		/**
		 * 将文件移动到上传目录中
		 * @param string $file
		 */
		private function move($file){
			if(!is_dir($this->path)) mkdir($this->path,0777,true);
			//新文件名
			$newFileName = $this->radomName($this->getSuffix($file['name']));
			//新路径 名 
			$newPath = $this->path.$newFileName;
			if(move_uploaded_file($file['tmp_name'], $newPath)){
				$this->upFiles[] = $newPath;
			}
			
		}
		
		/**
		 * 生成一个随机文件名
		 * @param string $suffix 后缀名
		 * @return string $name  返回一个随机名
		 */
		private function radomName($suffix){
			$name = time().'_'.mt_rand(0, 99999).'.'.$suffix;
			return $name;
		}
		
		/**
		 * 将数组重组因为原始的$_FILES数组不好处理
		 * 组装成:
		 * 				array(
		 * 				0=>array(
		 * 					'name'=>'xxx.jpg',
		 * 					'type'=>'image/jpg',
		 * 					.....
		 * 				),
		 * 				1=>array(
		 * 					'name'=>'xxx.jpg',
		 * 					'type'=>'image/jpg',
		 * 					.....
		 * 				),
		 * )
		 * @return array $fileArr
		 */
		private function resetArr(){
			//声明一个数组来保存
			$fileArr = array();
			//先将多文件上传的详细数组提取出来
			foreach($_FILES as $filesInfo){
				//判断当前name这个值是否为一个数组如果为一个数组那么就修改数组样式
				//如果不是一个数组那么就直接追加到数组最后
				if(is_array($filesInfo['name'])){
					foreach($filesInfo['name'] as $id=>$val){
						$fileArr[$id]['name'] = $val;
						$fileArr[$id]['type'] = $filesInfo['type'][$id];
						$fileArr[$id]['tmp_name'] = $filesInfo['tmp_name'][$id];
						$fileArr[$id]['error'] = $filesInfo['error'][$id];
						$fileArr[$id]['size'] = $filesInfo['size'][$id];
					}
				}else{
					$fileArr[] = $filesInfo;
				}
			}
			return $fileArr;
		}
		
		/**
		 * 过滤文件
		 * @param array $filter
		 * @param boolean
		 */
		private function filter(Array $filter){
			$suffix = $this->getSuffix($filter['name']);
			switch(true){
				case $filter['error']==4:
					$this->error[] = $filter['name'].'文件没有被上传<br />';
					return false;
				//先判断是否为一个上传上来的文件
				case !is_uploaded_file($filter['tmp_name']):
					$this->error[] = $filter['name'].'不是一个有效的上传文件<br />';
					return false;
				//判断文件是否超指定文件的大小
				case $filter['size'] > $this->allowSize:
					$this->error[] = $filter['name'].'文件超过指定大小<br />';
					return false;
				case $filter['error']==1:
				case $filter['error']==2:
					$this->error[] = $filter['name'].'文件过大<br />';
					return false;
				case $filter['error']==3:
					$this->error[] = $filter['name'].'文件可能过大只有部分被上传<br />';
					return false;
				case $filter['error']==6:
					$this->error[] = '找不到临时文件请联系管理员<br />';
					return false;
				case $filter['error']==7:
					$this->error[] = '文件写入失败请联系管理员<br />';
					return false;
				//判断是否允许上传的后缀
				case !array_key_exists($suffix, $this->allowType);
					$this->error[] = $filter['name'].'文件类型不允许上传<br />';
					return false;
				//判断是否允许上传的mime类型
				case !in_array($filter['type'],$this->allowType):
					$this->error[] = $filter['name'].'文件类型不允许上传<br />';
					return false;
				default:
					return true;
			}
		}

		
		
		function __get($pro){
			$str = '';
			//判断外外部如果访问的是error这个属性那么内部直接先将他格式化为一个字符串
			if($pro=='errors'){	
				foreach($this->error as $err){
					$str .= $err;
				}
			}
			return $str;
		}	
		/**
		 * 获得文件后缀名
		 * @param string $filename
		 * @return string $suffix
		 */
		public function getSuffix($filename){
			return ltrim(strrchr($filename, '.'),'.');
		}
	}